﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Commonality.Model;

namespace Commonality.Model.PLCControl
{
    public enum ESignalType
    {
        SIG_X,
        SIG_Y,
        SIG_F,
        SIG_G,
        SIG_M,
        SIG_D,
        SIG_T,
        SIG_NULL
    };
    public struct TPLCCell
    {
        public bool enable;         //使能;（暂时主要用于M，Y指令的使能）
        public ESignalType sigType; //信号类型
        public ushort stationNumber;//站号
        public ushort addr;         //地址
        public ushort offset;       //偏移值

        public string instruction;  //命令名称
    };
    public delegate void ImplementLADEx();
    public class CPLCControl
    {
        /// <summary>
        /// 起始站号        
        /// </summary>
        public static int workstationFirstAddress { get; set; }
        /// <summary>
        /// 使用站数
        /// </summary>
        public static int workstationNumOffset { get; set; }
        private static void InitPLCControl()
        {
            MitsubisiPlcModel.MitsubisiPlcModelIni(workstationFirstAddress, workstationNumOffset);
            PLCTimeGenerator.InitPLCTimeGenerator();
        }
        public static void SetLADProcessEx(ImplementLADEx lad)
        {
            InitPLCControl();
            PLCCirculation.PLCCirculationEvent += lad;
            PLCCirculation.Start_timer();
        }
        public static string OpenPLC(ushort StationNumber)
        {
            return MitsubisiPlcModel.Open(StationNumber);
        }
        public static void ClosePLC(ushort StationNumber)
        {
            MitsubisiPlcModel.Close(StationNumber);
        }
        public static void InitPlcCell(out TPLCCell cell, ESignalType type, ushort stationNumber, ushort address, ushort offset)
        {
            cell.enable = true;
            cell.sigType = type;
            cell.stationNumber = stationNumber;
            cell.addr = address;
            cell.offset = offset;

            cell.instruction = type.ToString() + stationNumber + address + offset;
        }
        public static void InitPlcCell(out TPLCCell cell, ESignalType type, ushort address, ushort offset)
        {
            cell.enable = true;
            cell.sigType = type;
            cell.stationNumber = 0;
            cell.addr = address;
            cell.offset = offset;

            cell.instruction = type.ToString() + address + offset;
        }
        public static void LAD_SetCell(TPLCCell cell)
        {
            #region 寄存器
            if (cell.instruction == "SIG_M" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "M" + cell.offset;
                MitsubisiPlcModel.WriteBit(cell.stationNumber, device, 1);
            }
            #endregion
            #region 通用输出
            if (cell.instruction == "SIG_Y" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "Y" + cell.addr + cell.offset;
                switch (cell.offset)
                {
                    case 10:
                        device = "Y" + cell.addr + "A";
                        break;
                    case 11:
                        device = "Y" + cell.addr + "B";
                        break;
                    case 12:
                        device = "Y" + cell.addr + "C";
                        break;
                    case 13:
                        device = "Y" + cell.addr + "D";
                        break;
                    case 14:
                        device = "Y" + cell.addr + "E";
                        break;
                    case 15:
                        device = "Y" + cell.addr + "F";
                        break;
                    default:
                        break;
                }
                MitsubisiPlcModel.WriteBit(cell.stationNumber, device, 1);
            }
            #endregion

        }
        public static void LAD_ResetCell(TPLCCell cell)
        {
            #region 寄存器
            if (cell.instruction == "SIG_M" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "M" + cell.offset;
                MitsubisiPlcModel.WriteBit(cell.stationNumber, device, 0);
            }
            #endregion
            #region 通用输出
            if (cell.instruction == "SIG_Y" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "Y" + cell.addr + cell.offset;
                MitsubisiPlcModel.WriteBit(cell.stationNumber, device, 0);
            }
            #endregion
            #region 定时器
            if (cell.instruction == "SIG_T" + cell.addr + cell.offset)
            {
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].enable = false;
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Time = 0;
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Time_Goal = 0;
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Over = false;
            }
            #endregion
        }
        public static byte LAD_CheckCell(TPLCCell cell)
        {
            #region 通用输入
            if (cell.instruction == "SIG_X" + cell.addr + cell.offset)
            {
                string device = "X" + cell.addr + cell.offset;
                return MitsubisiPlcModel.ReadBit(cell.stationNumber, device);
            }
            #endregion
            #region 通用输出
            if (cell.instruction == "SIG_Y" + cell.addr + cell.offset)
            {
                string device = "Y" + cell.addr + cell.offset;
                return MitsubisiPlcModel.ReadBit(cell.stationNumber, device);
            }
            #endregion
            #region 寄存器
            if (cell.instruction == "SIG_M" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "M" + cell.offset;
                return MitsubisiPlcModel.ReadBit(cell.stationNumber, device);
            }
            #endregion
            #region 定时器
            if (cell.instruction == "SIG_T" + cell.addr + cell.offset)
            {
                if (PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Over)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            #endregion
            return 0;
        }
        public static void LAD_SetDblCell(TPLCCell cell, short data)
        {
            #region 寄存器
            if (cell.instruction == "SIG_D" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "D" + cell.offset;
                MitsubisiPlcModel.WriteBytes(cell.stationNumber, device, data);
            }
            #endregion
        }
        public static short LAD_GetDblCell(TPLCCell cell)
        {
            #region 寄存器
            if (cell.instruction == "SIG_D" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "D" + cell.offset;
                return MitsubisiPlcModel.ReadBytes(cell.stationNumber, device);
            }

            #endregion
            return 0;
        }
        public static byte LAD_SetTCell(TPLCCell cell, uint nElapse)
        {
            if (cell.instruction == "SIG_T" + cell.addr + cell.offset)
            {
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].enable = true;               //定时器使能
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Time_Goal = nElapse;     //计数周期
            }
            return 0;
        }


        #region 缓存方式
        public static void LAD_SetCell_(TPLCCell cell)
        {
            #region 寄存器
            if (cell.instruction == "SIG_M" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "M" + cell.offset;

                switch (cell.stationNumber)
                {
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                        MitsubisiPlcModel.DxxxOutBuff[cell.stationNumber - 1][cell.offset - 800] = 1;
                        break;
                }


            }
            #endregion
            #region 通用输出
            if (cell.instruction == "SIG_Y" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "Y" + cell.addr + cell.offset;
                switch (cell.offset)
                {
                    case 10:
                        device = "Y" + cell.addr + "A";
                        break;
                    case 11:
                        device = "Y" + cell.addr + "B";
                        break;
                    case 12:
                        device = "Y" + cell.addr + "C";
                        break;
                    case 13:
                        device = "Y" + cell.addr + "D";
                        break;
                    case 14:
                        device = "Y" + cell.addr + "E";
                        break;
                    case 15:
                        device = "Y" + cell.addr + "F";
                        break;
                    default:
                        break;
                }
                MitsubisiPlcModel.WriteBit(cell.stationNumber, device, 1);
            }
            #endregion

        }
        public static void LAD_ResetCell_(TPLCCell cell)
        {
            #region 寄存器
            if (cell.instruction == "SIG_M" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "M" + cell.offset;

                switch (cell.stationNumber)
                {
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                        MitsubisiPlcModel.DxxxOutBuff[cell.stationNumber - 1][cell.offset - 800] = 0;
                        break;
                }
            }
            #endregion
            #region 通用输出
            if (cell.instruction == "SIG_Y" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "Y" + cell.addr + cell.offset;
                MitsubisiPlcModel.WriteBit(cell.stationNumber, device, 0);
            }
            #endregion
            #region 定时器
            if (cell.instruction == "SIG_T" + cell.addr + cell.offset)
            {
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].enable = false;
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Time = 0;
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Time_Goal = 0;
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Over = false;
            }
            #endregion
        }
        public static byte LAD_CheckCell_(TPLCCell cell)
        {
            #region 通用输入
            if (cell.instruction == "SIG_X" + cell.addr + cell.offset)
            {
                string device = "X" + cell.addr + cell.offset;
                return MitsubisiPlcModel.ReadBit(cell.stationNumber, device);
            }
            #endregion
            #region 通用输出
            if (cell.instruction == "SIG_Y" + cell.addr + cell.offset)
            {
                string device = "Y" + cell.addr + cell.offset;
                return MitsubisiPlcModel.ReadBit(cell.stationNumber, device);
            }
            #endregion
            #region 寄存器
            if (cell.instruction == "SIG_M" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "M" + cell.offset;
                byte ret = 0;
                switch (cell.stationNumber)
                {
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                        ret = (byte)MitsubisiPlcModel.MxxxIn[cell.stationNumber - 1][cell.offset - 800];
                        break;
                    default:
                        break;
                }


                return ret;
            }
            #endregion
            #region 定时器
            if (cell.instruction == "SIG_T" + cell.addr + cell.offset)
            {
                if (PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Over)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            #endregion
            return 0;
        }
        public static void LAD_SetDblCell_(TPLCCell cell, short data)
        {
            #region 寄存器
            if (cell.instruction == "SIG_D" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "D" + cell.offset;

                switch (cell.stationNumber)
                {
                    case 1:
                        if (cell.offset == 6)
                        {
                            MitsubisiPlcModel.DxOutBuff[cell.stationNumber - 1][cell.offset - 6] = data;
                        }
                        else
                        {
                            MitsubisiPlcModel.DxxxOutBuff[cell.stationNumber - 1][cell.offset - 530] = data;
                        }

                        break;
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                        MitsubisiPlcModel.DxxxOutBuff[cell.stationNumber - 1][cell.offset - 800] = data;
                        break;
                    default:
                        break;
                }


            }
            #endregion
        }
        public static short LAD_GetDblCell_(TPLCCell cell)
        {
            #region 寄存器
            if (cell.instruction == "SIG_D" + cell.stationNumber + cell.addr + cell.offset)
            {
                string device = "D" + cell.offset;
                byte ret = 0;
                switch (cell.stationNumber)
                {
                    case 1:
                        if (cell.offset == 6)
                        {
                            ret = (byte)MitsubisiPlcModel.DxIn[cell.stationNumber - 1][cell.offset - 6];
                        }
                        else
                        {
                            ret = (byte)MitsubisiPlcModel.DxxxIn[cell.stationNumber - 1][cell.offset - 530];
                        }
                        break;
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                        ret = (byte)MitsubisiPlcModel.DxxxIn[cell.stationNumber - 1][cell.offset - 800];
                        break;
                    default:
                        break;
                }


                return ret;
            }

            #endregion
            return 0;
        }
        public static byte LAD_SetTCell_(TPLCCell cell, uint nElapse)
        {
            if (cell.instruction == "SIG_T" + cell.addr + cell.offset)
            {
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].enable = true;               //定时器使能
                PLCTimeGenerator.PLC_T_Memory[cell.addr, cell.offset].PLC_Time_Goal = nElapse;     //计数周期
            }
            return 0;
        }
        #endregion
    }

    class PLCTimeGenerator
    {

        /// <summary>
        /// 计数单元结构
        /// </summary>
        public struct PLC_T
        {
            /// <summary>
            /// 计数器
            /// </summary>
            public uint PLC_Time;
            /// <summary>
            /// 计数器使能
            /// </summary>
            public bool enable;
            /// <summary>
            /// 定时时间
            /// </summary>
            public uint PLC_Time_Goal;
            /// <summary>
            /// 定时时间到时标志
            /// </summary>
            public bool PLC_Over;
        }

        /// <summary>
        /// 内部计数器
        /// </summary>
        public static PLC_T[,] PLC_T_Memory = new PLC_T[8, 16];


        private static System.Threading.Timer PLCthreadTimer;//一定要声明成局部变量以保持对Timer的引用，否则会被垃圾收集器回收
        public static void InitPLCTimeGenerator()
        {
            #region 初始化计数器资源
            for (int i = 0; i < 8; i++)                 //初始化
            {
                for (int j = 0; j < 16; j++)
                {
                    PLC_T_Memory[i, j].enable = false;
                    PLC_T_Memory[i, j].PLC_Time = 0;
                    PLC_T_Memory[i, j].PLC_Time_Goal = 0;
                    PLC_T_Memory[i, j].PLC_Over = false;
                }
            }
            #endregion
            #region 启动定时器
            Start_timer();
            #endregion
        }
        private static void Start_timer()
        {
            PLCthreadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(PLC_Timer_Tick), null, 0, 1000);
            //A表示要执行的方法,可以带参数也可以不带参数;B表示要给这A方法传递的参数，如果A方法不带参数，B可以为空
            //C表示这个方法调用之前等待的时间 ;D表示这个方法多久调用一次
            //dueTime：调用 callback 之前延迟的时间量（以毫秒为单位）。指定 Timeout.Infinite 以防止计时器开始计时。指定零 (0) 以立即启动计时器。
            //即过多长时间启动定时器，为-1则防止启动定时器
            //Period：调用 callback 的时间间隔（以毫秒为单位）。指定 Timeout.Infinite 可以禁用定期终止。
            //如果period为0或-1，dueTime大于0，则callback只执行一次
        }
        public static void Stop_timer()
        {
            if (PLCthreadTimer != null)
                PLCthreadTimer.Change(-1, -1);
            if (PLCthreadTimer != null)
                PLCthreadTimer.Dispose();//当不再需要定时器时，请用Dispose释放
        }
        private static void PLC_Timer_Tick(Object state)
        {
            //设置8*16个定时器供回调函数中使用
            for (int i = 0; i < 8; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    if (PLC_T_Memory[i, j].enable == true
                        && PLC_T_Memory[i, j].PLC_Time_Goal != 0
                        && PLC_T_Memory[i, j].PLC_Time != PLC_T_Memory[i, j].PLC_Time_Goal
                        && PLC_T_Memory[i, j].PLC_Over == false)                                //计时器使能-开始计数
                    {
                        PLC_T_Memory[i, j].PLC_Time++;                  //计数
                    }
                    else if (PLC_T_Memory[i, j].enable == true
                        && PLC_T_Memory[i, j].PLC_Time_Goal != 0
                        && PLC_T_Memory[i, j].PLC_Time == PLC_T_Memory[i, j].PLC_Time_Goal
                        && PLC_T_Memory[i, j].PLC_Over == false)                               //计数器计数到时-置位输出
                    {
                        PLC_T_Memory[i, j].PLC_Over = true;            //输出标志
                        PLC_T_Memory[i, j].PLC_Time = 0;
                    }
                }
            }
        }
    }
    class PLCCirculation
    {
        public static event ImplementLADEx PLCCirculationEvent;



        private static bool ScanComplement = true;





        private static int ScanTime = 100;

        private static System.Threading.Timer threadTimer;//一定要声明成局部变量以保持对Timer的引用，否则会被垃圾收集器回收

        public static void Start_timer()
        {
            threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(Thread_Timer_Tick), null, 0, ScanTime);


            //A表示要执行的方法,可以带参数也可以不带参数;B表示要给这A方法传递的参数，如果A方法不带参数，B可以为空
            //C表示这个方法调用之前等待的时间 ;D表示这个方法多久调用一次
            //dueTime：调用 callback 之前延迟的时间量（以毫秒为单位）。指定 Timeout.Infinite 以防止计时器开始计时。指定零 (0) 以立即启动计时器。
            //即过多长时间启动定时器，为-1则防止启动定时器
            //Period：调用 callback 的时间间隔（以毫秒为单位）。指定 Timeout.Infinite 可以禁用定期终止。
            //如果period为0或-1，dueTime大于0，则callback只执行一次

        }
        public static void Stop_timer()
        {
            if (threadTimer != null)
                threadTimer.Change(-1, -1);
            if (threadTimer != null)
                threadTimer.Dispose();//当不再需要定时器时，请用Dispose释放
        }
        private static void Thread_Timer_Tick(Object state)
        {
            //             if (!b_communication_success)//查看有没有通信成功
            //                 return;
            if (!ScanComplement)//如果定时器没有执行完成，则继续执行
                return;
            ScanComplement = false;
            #region 输入扫描
            //ReadMotionCardParameter();
            #endregion
            #region 逻辑计算
            ///回调逻辑计算
            PLCCirculationDelegate();
            ///回原点
            HomeInvolution();
            #endregion
            #region 输出刷新
            //WriteMotionCardParameter();

            #endregion
            ScanComplement = true;
        }


        private static void PLCCirculationDelegate()
        {
            try
            {
                if (PLCCirculationEvent != null)
                {
                    PLCCirculationEvent();
                }
            }
            catch 
            {
            }

        }

        private static void HomeInvolution()
        {

        }
        private static void ReadMotionCardParameter()
        {
            MitsubisiPlcModel.ReadBytesBlock(1, "D530").CopyTo(MitsubisiPlcModel.DxxxIn[0], 0);
            MitsubisiPlcModel.ReadBytesBlock(1, "D6").CopyTo(MitsubisiPlcModel.DxIn[0], 0);


            MitsubisiPlcModel.ReadBytesBlock(3, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[2], 0);
            MitsubisiPlcModel.ReadBytesBlock(4, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[3], 0);
            MitsubisiPlcModel.ReadBytesBlock(5, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[4], 0);
            MitsubisiPlcModel.ReadBytesBlock(6, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[5], 0);
            MitsubisiPlcModel.ReadBytesBlock(7, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[6], 0);
            MitsubisiPlcModel.ReadBytesBlock(8, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[7], 0);

            MitsubisiPlcModel.ReadBytesBlock(3, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[2], 0);
            MitsubisiPlcModel.ReadBytesBlock(4, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[3], 0);
            MitsubisiPlcModel.ReadBytesBlock(5, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[4], 0);
            MitsubisiPlcModel.ReadBytesBlock(6, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[5], 0);
            MitsubisiPlcModel.ReadBytesBlock(7, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[6], 0);
            MitsubisiPlcModel.ReadBytesBlock(8, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[7], 0);


            MitsubisiPlcModel.DxxxIn[0].CopyTo(MitsubisiPlcModel.DxxxOutBuff[0], 0);

            MitsubisiPlcModel.DxIn[0].CopyTo(MitsubisiPlcModel.DxOutBuff[0], 0);

            MitsubisiPlcModel.DxxxIn[2].CopyTo(MitsubisiPlcModel.DxxxOutBuff[2], 0);
            MitsubisiPlcModel.DxxxIn[3].CopyTo(MitsubisiPlcModel.DxxxOutBuff[3], 0);
            MitsubisiPlcModel.DxxxIn[4].CopyTo(MitsubisiPlcModel.DxxxOutBuff[4], 0);
            MitsubisiPlcModel.DxxxIn[5].CopyTo(MitsubisiPlcModel.DxxxOutBuff[5], 0);
            MitsubisiPlcModel.DxxxIn[6].CopyTo(MitsubisiPlcModel.DxxxOutBuff[6], 0);
            MitsubisiPlcModel.DxxxIn[7].CopyTo(MitsubisiPlcModel.DxxxOutBuff[7], 0);

            MitsubisiPlcModel.DxxxIn[2].CopyTo(MitsubisiPlcModel.DxxxOutBuff[2], 0);
            MitsubisiPlcModel.DxxxIn[3].CopyTo(MitsubisiPlcModel.DxxxOutBuff[3], 0);
            MitsubisiPlcModel.DxxxIn[4].CopyTo(MitsubisiPlcModel.DxxxOutBuff[4], 0);
            MitsubisiPlcModel.DxxxIn[5].CopyTo(MitsubisiPlcModel.DxxxOutBuff[5], 0);
            MitsubisiPlcModel.DxxxIn[6].CopyTo(MitsubisiPlcModel.DxxxOutBuff[6], 0);
            MitsubisiPlcModel.DxxxIn[7].CopyTo(MitsubisiPlcModel.DxxxOutBuff[7], 0);



            MitsubisiPlcModel.DxxxIn[0].CopyTo(MitsubisiPlcModel.DxxxOut[0], 0);

            //MitsubisiPlcModel.DxIn[0].CopyTo(MitsubisiPlcModel.DxOut[0], 0);

            MitsubisiPlcModel.DxxxIn[2].CopyTo(MitsubisiPlcModel.DxxxOut[2], 0);
            MitsubisiPlcModel.DxxxIn[3].CopyTo(MitsubisiPlcModel.DxxxOut[3], 0);
            MitsubisiPlcModel.DxxxIn[4].CopyTo(MitsubisiPlcModel.DxxxOut[4], 0);
            MitsubisiPlcModel.DxxxIn[5].CopyTo(MitsubisiPlcModel.DxxxOut[5], 0);
            MitsubisiPlcModel.DxxxIn[6].CopyTo(MitsubisiPlcModel.DxxxOut[6], 0);
            MitsubisiPlcModel.DxxxIn[7].CopyTo(MitsubisiPlcModel.DxxxOut[7], 0);

            MitsubisiPlcModel.DxxxIn[2].CopyTo(MitsubisiPlcModel.DxxxOut[2], 0);
            MitsubisiPlcModel.DxxxIn[3].CopyTo(MitsubisiPlcModel.DxxxOut[3], 0);
            MitsubisiPlcModel.DxxxIn[4].CopyTo(MitsubisiPlcModel.DxxxOut[4], 0);
            MitsubisiPlcModel.DxxxIn[5].CopyTo(MitsubisiPlcModel.DxxxOut[5], 0);
            MitsubisiPlcModel.DxxxIn[6].CopyTo(MitsubisiPlcModel.DxxxOut[6], 0);
            MitsubisiPlcModel.DxxxIn[7].CopyTo(MitsubisiPlcModel.DxxxOut[7], 0);
        }

        private static void WriteMotionCardParameter()
        {

            #region 站点1-D530
            //int[] dxxxOut1 = new int[32];
            for (int i = 0; i < 32; i++)
            {
                if (MitsubisiPlcModel.DxxxOutBuff[0][i] != MitsubisiPlcModel.DxxxOut[0][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[0][i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.WriteBytes(1, string.Format("D{0}", (530 + i)), MitsubisiPlcModel.DxxxOutBuff[0][i]);

                }
            }
            #endregion

            #region 站点1-D6
            for (int i = 0; i < 32; i++)
            {
                if (MitsubisiPlcModel.DxOutBuff[0][i] != MitsubisiPlcModel.DxOut[0][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxOut[0][i] = MitsubisiPlcModel.DxOutBuff[0][i];
                    MitsubisiPlcModel.WriteBytes(1, string.Format("D{0}", (6 + i)), MitsubisiPlcModel.DxOutBuff[0][i]);

                }
            }
            #endregion


            #region 3-8/D800
            for (int i = 0; i < 32; i++)
            {
                if (MitsubisiPlcModel.DxxxOutBuff[2][i] != MitsubisiPlcModel.DxxxOut[2][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[2][i] = MitsubisiPlcModel.DxxxOutBuff[2][i];
                    MitsubisiPlcModel.WriteBytes(3, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[2][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[3][i] != MitsubisiPlcModel.DxxxOut[3][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[3][i] = MitsubisiPlcModel.DxxxOutBuff[3][i];
                    MitsubisiPlcModel.WriteBytes(4, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[3][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[4][i] != MitsubisiPlcModel.DxxxOut[4][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[4][i] = MitsubisiPlcModel.DxxxOutBuff[4][i];
                    MitsubisiPlcModel.WriteBytes(5, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[4][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[5][i] != MitsubisiPlcModel.DxxxOut[5][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[5][i] = MitsubisiPlcModel.DxxxOutBuff[5][i];
                    MitsubisiPlcModel.WriteBytes(6, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[5][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[6][i] != MitsubisiPlcModel.DxxxOut[6][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[6][i] = MitsubisiPlcModel.DxxxOutBuff[6][i];
                    MitsubisiPlcModel.WriteBytes(7, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[6][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[7][i] != MitsubisiPlcModel.DxxxOut[7][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[7][i] = MitsubisiPlcModel.DxxxOutBuff[7][i];
                    MitsubisiPlcModel.WriteBytes(8, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[7][i]);

                }



                if (MitsubisiPlcModel.MxxxOutBuff[2][i] != MitsubisiPlcModel.MxxxOut[2][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[2][i] = MitsubisiPlcModel.MxxxOutBuff[2][i];
                    MitsubisiPlcModel.WriteBytes(3, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[2][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[3][i] != MitsubisiPlcModel.MxxxOut[3][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[3][i] = MitsubisiPlcModel.MxxxOutBuff[3][i];
                    MitsubisiPlcModel.WriteBytes(4, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[3][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[4][i] != MitsubisiPlcModel.MxxxOut[4][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[4][i] = MitsubisiPlcModel.MxxxOutBuff[4][i];
                    MitsubisiPlcModel.WriteBytes(5, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[4][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[5][i] != MitsubisiPlcModel.MxxxOut[5][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[5][i] = MitsubisiPlcModel.MxxxOutBuff[5][i];
                    MitsubisiPlcModel.WriteBytes(6, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[5][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[6][i] != MitsubisiPlcModel.MxxxOut[6][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[6][i] = MitsubisiPlcModel.MxxxOutBuff[6][i];
                    MitsubisiPlcModel.WriteBytes(7, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[6][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[7][i] != MitsubisiPlcModel.MxxxOut[7][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[7][i] = MitsubisiPlcModel.MxxxOutBuff[7][i];
                    MitsubisiPlcModel.WriteBytes(8, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[7][i]);

                }
            }
            #endregion



        }

    }



    class PLCCirculation2
    {
        public static event ImplementLADEx PLCCirculationEvent;



        private static bool ScanComplement = true;





        private static int ScanTime = 100;

        private static System.Threading.Timer threadTimer;//一定要声明成局部变量以保持对Timer的引用，否则会被垃圾收集器回收

        public static void Start_timer()
        {
            threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(Thread_Timer_Tick), null, 0, ScanTime);


            //A表示要执行的方法,可以带参数也可以不带参数;B表示要给这A方法传递的参数，如果A方法不带参数，B可以为空
            //C表示这个方法调用之前等待的时间 ;D表示这个方法多久调用一次
            //dueTime：调用 callback 之前延迟的时间量（以毫秒为单位）。指定 Timeout.Infinite 以防止计时器开始计时。指定零 (0) 以立即启动计时器。
            //即过多长时间启动定时器，为-1则防止启动定时器
            //Period：调用 callback 的时间间隔（以毫秒为单位）。指定 Timeout.Infinite 可以禁用定期终止。
            //如果period为0或-1，dueTime大于0，则callback只执行一次

        }
        public static void Stop_timer()
        {
            if (threadTimer != null)
                threadTimer.Change(-1, -1);
            if (threadTimer != null)
                threadTimer.Dispose();//当不再需要定时器时，请用Dispose释放
        }
        private static void Thread_Timer_Tick(Object state)
        {
            //             if (!b_communication_success)//查看有没有通信成功
            //                 return;
            if (!ScanComplement)//如果定时器没有执行完成，则继续执行
                return;
            ScanComplement = false;
            #region 输入扫描
            ReadMotionCardParameter();
            #endregion
            #region 逻辑计算
            ///回调逻辑计算
            PLCCirculationDelegate();
            ///回原点
            HomeInvolution();
            #endregion
            #region 输出刷新
            WriteMotionCardParameter();

            #endregion
            ScanComplement = true;
        }


        private static void PLCCirculationDelegate()
        {
            try
            {
                if (PLCCirculationEvent != null)
                {
                    PLCCirculationEvent();
                }
            }
            catch
            {
            }

        }

        private static void HomeInvolution()
        {

        }
        private static void ReadMotionCardParameter()
        {
            MitsubisiPlcModel.ReadBytesBlock(1, "D530").CopyTo(MitsubisiPlcModel.DxxxIn[0], 0);
            MitsubisiPlcModel.ReadBytesBlock(1, "D6").CopyTo(MitsubisiPlcModel.DxIn[0], 0);


            MitsubisiPlcModel.ReadBytesBlock(3, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[2], 0);
            MitsubisiPlcModel.ReadBytesBlock(4, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[3], 0);
            MitsubisiPlcModel.ReadBytesBlock(5, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[4], 0);
            MitsubisiPlcModel.ReadBytesBlock(6, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[5], 0);
            MitsubisiPlcModel.ReadBytesBlock(7, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[6], 0);
            MitsubisiPlcModel.ReadBytesBlock(8, "D800").CopyTo(MitsubisiPlcModel.DxxxIn[7], 0);

            MitsubisiPlcModel.ReadBytesBlock(3, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[2], 0);
            MitsubisiPlcModel.ReadBytesBlock(4, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[3], 0);
            MitsubisiPlcModel.ReadBytesBlock(5, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[4], 0);
            MitsubisiPlcModel.ReadBytesBlock(6, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[5], 0);
            MitsubisiPlcModel.ReadBytesBlock(7, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[6], 0);
            MitsubisiPlcModel.ReadBytesBlock(8, "M800").CopyTo(MitsubisiPlcModel.MxxxIn[7], 0);


            MitsubisiPlcModel.DxxxIn[0].CopyTo(MitsubisiPlcModel.DxxxOutBuff[0], 0);

            MitsubisiPlcModel.DxIn[0].CopyTo(MitsubisiPlcModel.DxOutBuff[0], 0);

            MitsubisiPlcModel.DxxxIn[2].CopyTo(MitsubisiPlcModel.DxxxOutBuff[2], 0);
            MitsubisiPlcModel.DxxxIn[3].CopyTo(MitsubisiPlcModel.DxxxOutBuff[3], 0);
            MitsubisiPlcModel.DxxxIn[4].CopyTo(MitsubisiPlcModel.DxxxOutBuff[4], 0);
            MitsubisiPlcModel.DxxxIn[5].CopyTo(MitsubisiPlcModel.DxxxOutBuff[5], 0);
            MitsubisiPlcModel.DxxxIn[6].CopyTo(MitsubisiPlcModel.DxxxOutBuff[6], 0);
            MitsubisiPlcModel.DxxxIn[7].CopyTo(MitsubisiPlcModel.DxxxOutBuff[7], 0);

            MitsubisiPlcModel.DxxxIn[2].CopyTo(MitsubisiPlcModel.DxxxOutBuff[2], 0);
            MitsubisiPlcModel.DxxxIn[3].CopyTo(MitsubisiPlcModel.DxxxOutBuff[3], 0);
            MitsubisiPlcModel.DxxxIn[4].CopyTo(MitsubisiPlcModel.DxxxOutBuff[4], 0);
            MitsubisiPlcModel.DxxxIn[5].CopyTo(MitsubisiPlcModel.DxxxOutBuff[5], 0);
            MitsubisiPlcModel.DxxxIn[6].CopyTo(MitsubisiPlcModel.DxxxOutBuff[6], 0);
            MitsubisiPlcModel.DxxxIn[7].CopyTo(MitsubisiPlcModel.DxxxOutBuff[7], 0);



            MitsubisiPlcModel.DxxxIn[0].CopyTo(MitsubisiPlcModel.DxxxOut[0], 0);

            //MitsubisiPlcModel.DxIn[0].CopyTo(MitsubisiPlcModel.DxOut[0], 0);

            MitsubisiPlcModel.DxxxIn[2].CopyTo(MitsubisiPlcModel.DxxxOut[2], 0);
            MitsubisiPlcModel.DxxxIn[3].CopyTo(MitsubisiPlcModel.DxxxOut[3], 0);
            MitsubisiPlcModel.DxxxIn[4].CopyTo(MitsubisiPlcModel.DxxxOut[4], 0);
            MitsubisiPlcModel.DxxxIn[5].CopyTo(MitsubisiPlcModel.DxxxOut[5], 0);
            MitsubisiPlcModel.DxxxIn[6].CopyTo(MitsubisiPlcModel.DxxxOut[6], 0);
            MitsubisiPlcModel.DxxxIn[7].CopyTo(MitsubisiPlcModel.DxxxOut[7], 0);

            MitsubisiPlcModel.DxxxIn[2].CopyTo(MitsubisiPlcModel.DxxxOut[2], 0);
            MitsubisiPlcModel.DxxxIn[3].CopyTo(MitsubisiPlcModel.DxxxOut[3], 0);
            MitsubisiPlcModel.DxxxIn[4].CopyTo(MitsubisiPlcModel.DxxxOut[4], 0);
            MitsubisiPlcModel.DxxxIn[5].CopyTo(MitsubisiPlcModel.DxxxOut[5], 0);
            MitsubisiPlcModel.DxxxIn[6].CopyTo(MitsubisiPlcModel.DxxxOut[6], 0);
            MitsubisiPlcModel.DxxxIn[7].CopyTo(MitsubisiPlcModel.DxxxOut[7], 0);
        }

        private static void WriteMotionCardParameter()
        {

            #region 站点1-D530
            //int[] dxxxOut1 = new int[32];
            for (int i = 0; i < 32; i++)
            {
                if (MitsubisiPlcModel.DxxxOutBuff[0][i] != MitsubisiPlcModel.DxxxOut[0][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[0][i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.WriteBytes(1, string.Format("D{0}", (530 + i)), MitsubisiPlcModel.DxxxOutBuff[0][i]);

                }
            }
            #endregion

            #region 站点1-D6
            for (int i = 0; i < 32; i++)
            {
                if (MitsubisiPlcModel.DxOutBuff[0][i] != MitsubisiPlcModel.DxOut[0][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxOut[0][i] = MitsubisiPlcModel.DxOutBuff[0][i];
                    MitsubisiPlcModel.WriteBytes(1, string.Format("D{0}", (6 + i)), MitsubisiPlcModel.DxOutBuff[0][i]);

                }
            }
            #endregion


            #region 3-8/D800
            for (int i = 0; i < 32; i++)
            {
                if (MitsubisiPlcModel.DxxxOutBuff[2][i] != MitsubisiPlcModel.DxxxOut[2][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[2][i] = MitsubisiPlcModel.DxxxOutBuff[2][i];
                    MitsubisiPlcModel.WriteBytes(3, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[2][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[3][i] != MitsubisiPlcModel.DxxxOut[3][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[3][i] = MitsubisiPlcModel.DxxxOutBuff[3][i];
                    MitsubisiPlcModel.WriteBytes(4, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[3][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[4][i] != MitsubisiPlcModel.DxxxOut[4][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[4][i] = MitsubisiPlcModel.DxxxOutBuff[4][i];
                    MitsubisiPlcModel.WriteBytes(5, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[4][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[5][i] != MitsubisiPlcModel.DxxxOut[5][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[5][i] = MitsubisiPlcModel.DxxxOutBuff[5][i];
                    MitsubisiPlcModel.WriteBytes(6, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[5][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[6][i] != MitsubisiPlcModel.DxxxOut[6][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[6][i] = MitsubisiPlcModel.DxxxOutBuff[6][i];
                    MitsubisiPlcModel.WriteBytes(7, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[6][i]);

                }
                if (MitsubisiPlcModel.DxxxOutBuff[7][i] != MitsubisiPlcModel.DxxxOut[7][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.DxxxOutBuff[0][i];
                    MitsubisiPlcModel.DxxxOut[7][i] = MitsubisiPlcModel.DxxxOutBuff[7][i];
                    MitsubisiPlcModel.WriteBytes(8, string.Format("D{0}", (800 + i)), MitsubisiPlcModel.DxxxOutBuff[7][i]);

                }



                if (MitsubisiPlcModel.MxxxOutBuff[2][i] != MitsubisiPlcModel.MxxxOut[2][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[2][i] = MitsubisiPlcModel.MxxxOutBuff[2][i];
                    MitsubisiPlcModel.WriteBytes(3, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[2][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[3][i] != MitsubisiPlcModel.MxxxOut[3][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[3][i] = MitsubisiPlcModel.MxxxOutBuff[3][i];
                    MitsubisiPlcModel.WriteBytes(4, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[3][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[4][i] != MitsubisiPlcModel.MxxxOut[4][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[4][i] = MitsubisiPlcModel.MxxxOutBuff[4][i];
                    MitsubisiPlcModel.WriteBytes(5, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[4][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[5][i] != MitsubisiPlcModel.MxxxOut[5][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[5][i] = MitsubisiPlcModel.MxxxOutBuff[5][i];
                    MitsubisiPlcModel.WriteBytes(6, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[5][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[6][i] != MitsubisiPlcModel.MxxxOut[6][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[6][i] = MitsubisiPlcModel.MxxxOutBuff[6][i];
                    MitsubisiPlcModel.WriteBytes(7, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[6][i]);

                }
                if (MitsubisiPlcModel.MxxxOutBuff[7][i] != MitsubisiPlcModel.MxxxOut[7][i])
                {
                    //dxxxOut1[i] = MitsubisiPlcModel.MxxxOutBuff[0][i];
                    MitsubisiPlcModel.MxxxOut[7][i] = MitsubisiPlcModel.MxxxOutBuff[7][i];
                    MitsubisiPlcModel.WriteBytes(8, string.Format("M{0}", (800 + i)), MitsubisiPlcModel.MxxxOutBuff[7][i]);

                }
            }
            #endregion



        }

    }
}
